package com.pe.pgn.clubpgn.service.impl;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.pe.pgn.clubpgn.dao.EstacionDao;
import com.pe.pgn.clubpgn.dao.TarjetaPersonaDao;
import com.pe.pgn.clubpgn.dao.TipoTarjetaPersonaDao;
import com.pe.pgn.clubpgn.domain.ClpbEstacion;
import com.pe.pgn.clubpgn.domain.ClpbTarjetaPersona;
import com.pe.pgn.clubpgn.domain.ClpdTipoTarjetaPersona;
import com.pe.pgn.clubpgn.domain.beans.BNRango;
import com.pe.pgn.clubpgn.domain.beans.BNTarjetaPersona;
import com.pe.pgn.clubpgn.service.TarjetaPersonaService;

@Service("tarjetaPersonaService")
public class TarjetaPersonaServiceImpl extends GenericManagerImpl<ClpbTarjetaPersona, Long>
		implements TarjetaPersonaService {

	@Autowired
	private TarjetaPersonaDao tarjetaPersonaDao;
	
	@Autowired
	private TipoTarjetaPersonaDao tipoTarjetaPersonaDao;
	
	@Autowired 
	private EstacionDao estacionDao;

	public List<ClpbTarjetaPersona> obtenerTarjetasPersonas() {
		return tarjetaPersonaDao.obtenerTarjetasPersonas();
	}

	public ClpbTarjetaPersona obtenerTarjetaPersona(Long id) {
		return tarjetaPersonaDao.obtenerTarjetaPersona(id);
	}

	public void guardarTarjetaPersona(ClpbTarjetaPersona tarjetaPersona) {
		tarjetaPersonaDao.guardarTarjetaPersona(tarjetaPersona);
	}

	public void eliminarTarjetaPersona(Long id) {
		tarjetaPersonaDao.eliminarTarjetaPersona(id);
	}

	public void guardarGrupoTarjetasPersonas(BNTarjetaPersona tarjetaPersona) {
		tarjetaPersonaDao.guardarGrupoTarjetasPersonas(tarjetaPersona);
	}
	
	public boolean existeRango(BNTarjetaPersona tarjetaPersona){

		return tarjetaPersonaDao.existeRango(tarjetaPersona);
	}

	public List<ClpdTipoTarjetaPersona> obtenerTiposTarjetasPersonas(){
		return tipoTarjetaPersonaDao.obtenerTiposTarjetasPersonas();
	}
	
	public BNTarjetaPersona obtenerMaximoCodigoTarjetaPersona() {
		
		BigDecimal maximoCodigo = tarjetaPersonaDao.obtenerMaximoCodigoTarjetaPersona();
		maximoCodigo = maximoCodigo.add(BigDecimal.ONE);
 
		BNTarjetaPersona tarjetaPersona = new BNTarjetaPersona();
		tarjetaPersona.setNumeroInicio(maximoCodigo);
		return tarjetaPersona;
	}
	
	public List<ClpbEstacion> obtenerEstaciones(){
		return estacionDao.obtenerEstaciones();
	}
	
	public List<BNRango> obtenerRangosTarjetaDisponibles(){
		
		BigDecimal primero = BigDecimal.ZERO;

		List<String> listaTarjetasDisponibles = tarjetaPersonaDao.obtenerListaTarjetaNoAsignadas();
		List<BigDecimal> listaExtremos = new ArrayList<BigDecimal>();
		
		for(Iterator<String> iter = listaTarjetasDisponibles.iterator(); iter.hasNext(); ){
			
			String codigo = iter.next();
			BigDecimal siguiente = new BigDecimal(codigo.substring(1, codigo.length()));
			
			if(siguiente.subtract(primero) != BigDecimal.ONE 
					|| siguiente.compareTo(BigDecimal.ONE) == 0){
				
				if(!listaExtremos.isEmpty()){
					listaExtremos.add(primero);
				}
				listaExtremos.add(siguiente);
			}	
			primero = siguiente;
			
			if(!iter.hasNext()){
				listaExtremos.add(siguiente);
			}
		} 
		
		List<BNRango> listaRangos = obtenerListaRangos(listaExtremos);
		return listaRangos;
	}
	
	public List<BNRango> obtenerListaRangos(List<BigDecimal> listaExtremos){
		
		List<BNRango> listaRangos = new ArrayList<BNRango>();
		for(int i = 0; i < listaExtremos.size(); i++){
			
			BNRango rango = new BNRango();
			rango.setInicio(listaExtremos.get(i++));
			rango.setFin(listaExtremos.get(i));
			
			listaRangos.add(rango);
		}
		return listaRangos;
	}
	
	public boolean existenCodigosAsignadosEnRango(BNTarjetaPersona tarjetaPersona){
		return tarjetaPersonaDao.existenCodigosAsignadosEnRango(tarjetaPersona);
	}
	
	public void asignarTarjetasPersonas(BNTarjetaPersona tarjetaPersona){
		tarjetaPersonaDao.asignarTarjetasPersonas(tarjetaPersona);
	}

	public List<ClpbTarjetaPersona> buscarTarjetas(
			String coCodigoTarjetaPersona, Long coEstacion, String deNombre, String fechaVigencia, String estadoTarjeta, String stStrAnulada) {
		return tarjetaPersonaDao.buscarTarjetas(coCodigoTarjetaPersona, coEstacion, deNombre,  fechaVigencia, estadoTarjeta, stStrAnulada);
	}

	public List<BNRango> obtenerRangosTarjetaDisponiblesPorEstacion(
			Long coEstacion) {
		
		BigDecimal primero = BigDecimal.ZERO;

		coEstacion = coEstacion == null?-1:coEstacion;
		List<String> listaTarjetasDisponibles = tarjetaPersonaDao.obtenerListaTarjetaNoAsignadosClientes(coEstacion);
		List<BigDecimal> listaExtremos = new ArrayList<BigDecimal>();
		
		for(Iterator<String> iter = listaTarjetasDisponibles.iterator(); iter.hasNext(); ){
			
			String codigo = iter.next();
			BigDecimal siguiente = new BigDecimal(codigo.substring(1, codigo.length()));
			
			if(siguiente.subtract(primero) != BigDecimal.ONE 
					|| siguiente.compareTo(BigDecimal.ONE) == 0){
				
				if(!listaExtremos.isEmpty()){
					listaExtremos.add(primero);
				}
				listaExtremos.add(siguiente);
			}	
			primero = siguiente;
			
			if(!iter.hasNext()){
				listaExtremos.add(siguiente);
			}
		} 
		
		List<BNRango> listaRangos = obtenerListaRangos(listaExtremos);
		return listaRangos;
	}

	public void reasignarTarjetasPersonas(BNTarjetaPersona tarjetaPersona) {
		tarjetaPersonaDao.reasignarTarjetasPersonas(tarjetaPersona);
	}

	public boolean existenCodigosAsignadosEnRangoPorEstacion(BNTarjetaPersona tarjetaPersona) {
		return tarjetaPersonaDao.existenCodigosAsignadosEnRangoPorEstacion(tarjetaPersona);
	}
}
